﻿var Eci = Eci || {}
Eci.Control = Eci.Control || {}

/**
 * 上传控件
 *
 */
Eci.Control.DownloadControl = function (connOpt, options) {
  var obj = {
    /**
     * 上传控件窗体id
     */
    id: 'eci-upload-dialog',

    /**
     * 上传文件列表
     */
    uploadFiles: [],

    /**
     * 当前文件索引
     */
    currIndex: 0,

    /**
     * 最后一批文件的索引
     */
    lastIndex: 0,

    /**
     * 上传控件容器
     */
    uploadBoxId: 'upload',

    /**
     * 上传控件容器
     */
    zipName: 'newFile',

    /**
     * WebSocket对象
     */
    channel: null,

    /**
     * 是否实名保存文件
     */
    IsRealName: null,

    /**
     * 是否启用单进度条
     */
    IsSingleProgress: false,

    /**
     * 单进度条id
     */
    progressContainerId: null,

    /**
     * 单进度条id
     */
    fileNameSource: 'source',

    /**
     * 把上传控件的HTML添加到指定元素里
     */
    init: function (connOpt, options) {
      //  上传文件控件参数
      if (options.complete) {
        this.complete = options.complete
      }

      if (options.close) {
        this.close = options.close
      }

      if (options.error) {
        this.error = options.error
      }

      if (connOpt.fileNameSource) {
        this.fileNameSource = connOpt.fileNameSource
      }

      this.currIndex = 0
      this.lastIndex = 0
      this.IsRealName = connOpt.IsRealName
      if (connOpt.IsSingleProgress) this.IsSingleProgress = connOpt.IsSingleProgress
    },

    /**
     * 外部调用的关闭窗体事件
     */
    close: null,

    /**
     * 给指定id的元素添加上传控件的HTML
     */
    appendHTML: function () {
      var i = 6

      while (i--) {
        //  给上传控件容器随机生成一个id
        this.uploadBoxId += Math.floor(Math.random() * 16.0).toString(16)
      }

      var maskDiv = "<div id='mask-" + this.id + "' class='eci-progressbar-bg' style='display:none;'></div>"
      jQuery('body').append(maskDiv)

      //  把上传控件添加到body标签里
      var uploadDiv =
        '<div class="eci-progressbar" style="display:none;"><div id="' +
        this.id +
        '" class="eci-progressbar-container-box"></div></div>'
      jQuery('body').append(uploadDiv)

      var header = document.getElementById('mask-' + this.id)
      document.addEventListener('scroll', function (e) {
        window.scrollY >= header.offsetTop ? header.classList.add('sticky') : header.classList.remove('sticky')
      })
    },

    /**
     * 验证文件名
     */
    fileValid: null,

    /**
     * 连接次数
     */
    reConnectTimes: 0,

    /**
     * 连接次数
     */
    isUploading: false,

    /**
     * 集线器名称
     */
    channelName: 'downloadhub',

    /**
     * 重连服务器
     */
    reConnectServer: function () {
      this.channel.reConnectServer()
    },

    /**
     * 文件续传
     */
    continueUpload: function (file, channel) {
      setTimeout(function () {
        file.ContinueUpload(channel, 'Handler.UploadFile')
      }, 200)
    },

    errorFile: function (evt) {
      for (var i = 0, fileLen = this.uploadFiles.length; i < fileLen; i++) {
        var file = this.uploadFiles[i]

        if (!file.IsComplete) {
          file.IsStop = true
          var eciProgressNum = 'eci_p_num_' + file.ID
          $('#' + eciProgressNum).html('Reconnecting')
          var closedSector = $('#eci_p_close_' + file.ID)
          closedSector.removeClass('icon-icon_No')
          closedSector.addClass('icon-sup-0039-go-back')
        }
      }
    },

    /**
     * 连接服务器
     */
    connectServer: function (hubName) {
      var that = this

      var channel = new Eci.Communication.Websocket(this.channelName, hubName)
      //  WebSocket连接
      channel.connected = function (evt) {
        that.reConnectTimes = 0

        if (options.connected) {
          options.connected(evt)
        }

        that.connected(hubName)
      }

      //  接收异常信息
      channel.error = function (evt) {
        if (evt.message) {
          console.log(evt.message)
          that.errorFile(evt)
          that.error(Eci.DownloadResource.NotConnected)
        } else {
          console.error(evt)
          that.error(evt.Error)
        }
      }

      //  WebSocket关闭
      channel.disposed = function (evt) {
        if (options.disposed) {
          options.disposed(evt)
        }

        if (that.isUploading) {
          for (var i = 0, fileLen = that.uploadFiles.length; i < fileLen; i++) {
            var file = that.uploadFiles[i]
            if (!file.IsComplete) {
              $('#' + 'eci_p_num_' + file.ID).html(Eci.DownloadResource.ConnectionInterrupted)
            }
          }
        }
      }

      //  接收WebSocket信息
      channel.reconnected = function (evt) {
        that.reconnected(hubName)
      }

      return channel
    },

    /**
     * 一批文件都上传完毕事件
     */
    complete: function (files) {},

    /**
     * 显示上传容器
     */
    show: function (files) {
      $('#' + this.id).show()

      //  在网页里添加上传控件窗体
      this.appendHTML()

      //  建立WebSocket连接
      this.upload(files)
    },

    /**
     * 在一个拖动过程中，释放鼠标键时触发此事件
     */
    showDownload: function (files) {
      this.show(files)
    },

    /**
     * 隐藏上传容器，并且清空容器
     */
    hide: function () {
      for (var i = 0; i < this.fileServers.length; i++) {
        this.fileServers[i].channel.close()
        this.fileServers[i].channel = null
      }

      this.fileServers = []

      this.currIndex = 0
      this.lastIndex = 0
      $('#' + this.id).hide() //  隐藏容器
      $('#mask-' + this.id).hide() //  隐藏容器
      this.clearUploadItems() //  清空容器
      this.close()
    },

    /**
     * 获得上传容器
     */
    getUploadBox: function () {
      return document.getElementById('eci-upload-dialog-container')
    },

    /**
     * 在一个拖动过程中，释放鼠标键时触发此事件
     */
    upload: function (files) {
      if (files.length > 0) {
        this.progressContainerId = Math.floor(Math.random() * 0x10000).toString()
        this.onFileOpen(files)
      }
    },

    /**
     * 上传容器添加文件元素
     */
    addUploadItem: function (info) {
      var progressbarId = info.ID
      var that = this

      if (!this.IsSingleProgress) {
        var eciProgressContainer = 'eci_progressbar_container_' + progressbarId
        var eciProgressText = 'eci_p_text_' + progressbarId
        var eciProgress = 'eci_p_progress_' + progressbarId
        var eciProgressNum = 'eci_p_num_' + progressbarId
        var eciProgressClose = 'eci_p_close_' + progressbarId

        $('#' + this.id).append(
          '<div id="' +
            eciProgressContainer +
            '" class="eci-progressbar-container" ><div class="icon-icon_Download eci-progressbar-icon"></div><div class="eci-progressbar-body"><div class="eci-progressbar-body-top eci-progressbar-ver-mid"><span id="' +
            eciProgressText +
            '"></span></div><div class="eci-progressbar-body-center"><div id="' +
            eciProgress +
            '" class="eci-progressbar-length"></div></div><div class="eci-progressbar-body-bottom eci-progressbar-ver-mid"><span  id="' +
            eciProgressNum +
            '"></span></div></div><div class="eci-progressbar-right"><div id="' +
            eciProgressClose +
            '" class="icon-icon_No eci-progressbar-close"></div></div></div>'
        )
        //  进度条显示上传进度
        if (!this.IsSingleProgress) $('#' + eciProgressText).html(info.FileName)
        document.getElementById(eciProgress).style.width = 0
        $('#' + eciProgressNum).empty()

        $('#' + eciProgressClose).click(function () {
          that.clearUploadItem(this.id)
          $(this).unbind('click')
        })
      }

      info._channel = info.channel
      info.OnDownloadCompleted = function (data) {
        var fileLen = that.uploadFiles.length

        var isCompleted = true
        //  这批文件发送到外部事件调用
        for (var j = 0; j < fileLen; j++) {
          if (!that.uploadFiles[j].IsComplete) {
            isCompleted = false
          }
        }

        if (isCompleted) {
          if (that.IsSingleProgress) {
            that.decompressingProcess(that.uploadFiles.length === 1)
          } else {
            for (var i = 0; i < that.uploadFiles.length; i++) {
              that.decompressingProcess(that.uploadFiles[i])
            }
          }

          var blob = that.uploadFiles[0].Blob
          that.currentIndex = 0
          that.blobURL = URL.createObjectURL(blob)
          var alink = document.createElement('a')
          alink.style.setProperty('display', 'none')
          document.body.appendChild(alink)
          alink.href = that.blobURL
          alink.download = that.uploadFiles[0].FileName
          alink.click()

          that.complete(that.uploadFiles)

          if (that.IsSingleProgress) {
            that.decompressedProcess()
          } else {
            for (var i = 0; i < that.uploadFiles.length; i++) {
              that.decompressedProcess(that.uploadFiles[i])
            }
          }

          that.hide()
          setTimeout(function () {
            window.URL.revokeObjectURL(that.blobURL)
            that.blobURL = null
          }, 5000)
          document.body.removeChild(alink)
          // zip.createWriter(new zip.BlobWriter(), function (writer) {
          // that.zipWriter = writer;
          // that.createZip();
          // }, function onerror(message) {
          // console.error(message);
          // });
        }
      }

      info.OnDownloadData()
    },

    addSingleUploadItem: function () {
      var fileCount = this.uploadFiles.length
      var progressbarId = this.progressContainerId
      var eciProgressContainer = 'eci_progressbar_container_' + progressbarId
      var eciProgressText = 'eci_p_text_' + progressbarId
      var eciProgress = 'eci_p_progress_' + progressbarId
      var eciProgressNum = 'eci_p_num_' + progressbarId
      var eciProgressClose = 'eci_p_close_' + progressbarId

      $('#' + this.id).append(
        '<div id="' +
          eciProgressContainer +
          '" class="eci-progressbar-container" ><div class="icon-icon_Download eci-progressbar-icon"></div><div class="eci-progressbar-body"><div class="eci-progressbar-body-top eci-progressbar-ver-mid"><span id="' +
          eciProgressText +
          '"></span></div><div class="eci-progressbar-body-center"><div id="' +
          eciProgress +
          '" class="eci-progressbar-length"></div></div><div class="eci-progressbar-body-bottom eci-progressbar-ver-mid"><span  id="' +
          eciProgressNum +
          '"></span></div></div><div class="eci-progressbar-right"><div id="' +
          eciProgressClose +
          '" class="icon-icon_No eci-progressbar-close"></div></div></div>'
      )
      //  进度条显示上传进度
      if (fileCount === 1) {
        $('#' + eciProgressText).html(Eci.DownloadResource.SingletonSingleFile.replace('$source$', this.fileNameSource))
      } else {
        $('#' + eciProgressText).html(
          Eci.DownloadResource.SingletonMultiFiles.replace('$file_count$', fileCount).replace(
            '$source$',
            this.fileNameSource
          )
        )
      }

      document.getElementById(eciProgress).style.width = 0
      $('#' + eciProgressNum).empty()
      var that = this
      $('#' + eciProgressClose).click(function () {
        for (var i = 0; i < that.uploadFiles.length; i++) {
          that.uploadFiles[i].IsStop = true
        }
        that.hide()
        $(this).unbind('click')
      })
    },

    /**
     * 清空上传容器
     */
    clearUploadItem: function (id) {
      var index = $("div[id^='eci_p_close_']").index($('#' + id))
      var id2 = id.replace('eci_p_close_', '')
      var containerId = 'eci_progressbar_container_' + id2

      $('#' + containerId).animate(
        {
          height: 0
        },
        500,
        '',
        function () {
          $('#' + containerId).remove()
        }
      )

      this.uploadFiles[index].IsStop = true
      var len = this.uploadFiles.length

      for (var i = len - 1; i >= 0; i--) {
        if (this.uploadFiles[i].ID == id2) {
          if (this.uploadFiles[i].IsComplete) {
            //  删除已经上传完成的文件需要减一
            this.currIndex--
          }

          if (this.lastIndex > i) {
            //  删除前几批上传完成的文件需要减一
            this.lastIndex--
          }

          //  删除当前文件
          this.uploadFiles.splice(i, 1)

          break
        }
      }

      for (var j = this.fileServers.length - 1; j >= 0; j--) {
        var isFileServer = false
        var fileServer = this.fileServers[j]

        for (var k = 0; k < this.uploadFiles.length; k++) {
          if (this.uploadFiles[k].channel === fileServer.channel) {
            isFileServer = true
          }
        }

        if (!isFileServer) {
          fileServer.channel.close()
          fileServer.channel = null
          this.fileServers.splice(j, 1)
        }
      }

      if (len === 1 || this.IsSingleProgress) {
        this.currIndex = 0
        this.lastIndex = 0
        $('#' + this.id).hide() //  隐藏容器
        $('#mask-' + this.id).hide() //  隐藏容器
        this.clearUploadItems() //  清空容器
        this.close()
      }
    },

    /**
     * 清空上传容器
     */
    stopUpload: function (id) {
      var closedSector = $('#' + id)

      var index = $("div[id^='eci_p_close_']").index(closedSector)
      var file = this.uploadFiles[index]

      if (closedSector.hasClass('icon-icon_No')) {
        file.IsStop = true

        //var id2 = id.replace("eci_p_close_", "");

        closedSector.removeClass('icon-icon_No')
        closedSector.addClass('icon-sup-0039-go-back')
      } else {
        file.IsStop = false
        file.IsContinue = true
        var channel = this.channel
        setTimeout(function () {
          file.ContinueUpload(channel, 'Handler.UploadFile')
        }, 200)

        closedSector.addClass('icon-icon_No')
        closedSector.removeClass('icon-sup-0039-go-back')
      }
    },

    /**
     * 清空上传容器
     */
    clearUploadItems: function () {
      this.uploadFiles = []
      this.reConnectTimes = 0
      this.currIndex = 0
      this.lastIndex = 0
      this.progressContainerId = null

      $('.eci-progressbar-container').remove()
      $('#eci-upload-dialog').remove()
      $('#mask-eci-upload-dialog').remove()
      $('.eci-progressbar').remove()
    },

    connected: function (hubName) {
      for (var i = 0; i < this.fileServers.length; i++) {
        var fileServer = this.fileServers[i]

        if (fileServer.hubName === hubName) {
          for (var j = 0; j < fileServer.Files.length; j++) {
            var info = fileServer.Files[j]
            info.DataBuffer = ''
            this.onUploadData(info)
          }

          break
        }
      }
    },

    reconnected: function (hubName) {
      for (var i = 0; i < this.fileServers.length; i++) {
        var fileServer = this.fileServers[i]

        if (fileServer.hubName === hubName) {
          for (var j = 0; j < fileServer.Files.length; j++) {
            var info = fileServer.Files[j]

            if (info.PageIndex < info.Pages) {
              info.IsStop = false
              info.OnDownloadData()
            }
          }

          break
        }
      }
    },

    onUploadData: function (info) {
      this.addUploadItem(info)
    },

    setZipName: function (zipName) {
      this.zipName = zipName
    },

    fileServers: [],

    /**
     * 打开拖入上传容器的文件
     */
    onFileOpen: function (files) {
      var that = this

      $('#mask-' + that.id).show()
      $('#eci-upload-dialog').parent().show()

      if (files.length > 0) {
        for (var i = 0; i < files.length; i++) {
          var file = files[i]

          var info = new Eci.IO.File(file)

          if (this.IsSingleProgress) {
            info.ContainerId = this.progressContainerId
          }

          var fileServer = { hubName: 'hub_' + file.ServerFileID, hub: null, Files: [] }

          for (var j = 0; j < this.fileServers.length; j++) {
            var fServer = this.fileServers[j]

            if (fServer.hubName === fileServer.hubName) {
              fServer.Files.push(info)
              info.channel = fServer.channel
              break
            }
          }

          if (typeof info.channel === 'undefined') {
            $.signalR[fileServer.hubName] = $.hubConnection('/signalr', { useDefaultPath: false })
            $.signalR[fileServer.hubName].createHubProxies()
            // $.extend($.signalR, $.signalR[fileServer.hubName].createHubProxies())
            fileServer.hub = $.signalR[fileServer.hubName]
            fileServer.url = file.Url
            fileServer.channel = this.connectServer(fileServer.hubName)
            fileServer.Files.push(info)
            this.fileServers.push(fileServer)
            info.channel = fileServer.channel
          }

          var nameArray = file.FullName.split('\\')

          if (file.FullName.substring(0, 1) === '\\') {
            info.FullName = file.FullName.substring(1)
          } else {
            info.FullName = file.FullName
          }

          info.FileName = nameArray[nameArray.length - 1]
          info.RealPath = file.RealPath
          info.Pages = 0
          info.parameters = {
            PageIndex: 0,
            FileID: info.FileID
          }

          info.UploadProcess = function (file) {
            that.onUploadProcess(file)
          }
          this.uploadFiles.push(info)
        }
      }

      if (this.IsSingleProgress) {
        this.addSingleUploadItem()
      }

      for (var k = 0; k < this.fileServers.length; k++) {
        this.fileServers[k].channel.connect(this.fileServers[k].url)
      }
    },

    /**
     * 进度条显示上传进度
     */
    onUploadProcess: function (file) {
      var progressbarId = file.ID

      if (file.ContainerId) {
        progressbarId = file.ContainerId
      }

      var eciProgress = 'eci_p_progress_' + progressbarId
      var eciProgressNum = 'eci_p_num_' + progressbarId

      var width
      var html
      var byteLength = 0

      if (this.IsSingleProgress) {
        var fileSize = 0,
          pageIndex = 0,
          pages = 0
        for (var i = 0; i < this.uploadFiles.length; i++) {
          for (var k = 0; k < this.uploadFiles[i].DataBytes.length; k++) {
            byteLength += this.uploadFiles[i].DataBytes[k].length
          }

          fileSize += this.uploadFiles[i].FileSize
          pageIndex += this.uploadFiles[i].PageIndex
          pages += this.uploadFiles[i].Pages
        }

        html = Math.round((byteLength / 1024) * 100) / 100 + 'KB / ' + Math.round((fileSize / 1024) * 100) / 100 + 'KB'
        width = (pageIndex / pages) * $('.eci-progressbar-body-center').width()
      } else {
        for (var j = 0; j < file.DataBytes.length; j++) {
          byteLength += file.DataBytes[j].length
        }
        html =
          Math.round((byteLength / 1024) * 100) / 100 + 'KB / ' + Math.round((file.FileSize / 1024) * 100) / 100 + 'KB'
        width = (file.PageIndex / file.Pages) * $('.eci-progressbar-body-center').width()
      }

      if (document.getElementById(eciProgress)) {
        document.getElementById(eciProgress).style.width = width + 'px'
        $('#' + eciProgressNum).html(html)
      }
    },

    /**
     * Singleton模式时, file 类型为 bool
     * 非Singleton模式时, file 类型为 Eci.IO.File
     * @param {} file
     * @returns {}
     */
    decompressingProcess: function (file) {
      var eciProgressNum
      var eciProgressText

      if (this.IsSingleProgress) {
        eciProgressNum = 'eci_p_num_' + this.progressContainerId
        eciProgressText = 'eci_p_text_' + this.progressContainerId

        if (file) {
          $('#' + eciProgressNum).html(Eci.DownloadResource.SingletonSingleFileStatus)
          $('#' + eciProgressText).html(
            Eci.DownloadResource.SingletonSingleFileComplete.replace('$source$', this.fileNameSource)
          )
        } else {
          $('#' + eciProgressNum).html(Eci.DownloadResource.SingletonSingleFileStatus)
          $('#' + eciProgressText).html(
            Eci.DownloadResource.SingletonMultiFilesComplete.replace('$file_count$', this.uploadFiles.length).replace(
              '$source$',
              this.fileNameSource
            )
          )
        }
      } else {
        var progressbarId = file.ID
        eciProgressNum = 'eci_p_num_' + progressbarId
        $('#' + eciProgressNum).html(Eci.DownloadResource.Decompressing.replace('$source$', this.fileNameSource))
      }
    },

    decompressedProcess: function (file) {
      var eciProgressNum

      if (this.IsSingleProgress) {
        eciProgressNum = 'eci_p_num_' + this.progressContainerId
      } else {
        var progressbarId = file.ID
        eciProgressNum = 'eci_p_num_' + progressbarId
      }

      $('#' + eciProgressNum).html(Eci.DownloadResource.Decompressed.replace('$source$', this.fileNameSource))
    },

    currentIndex: 0,

    createZip: function () {
      var that = this
      var file = that.uploadFiles[that.currentIndex++]
      console.log('create zip')
      this.zipWriter.add(file.FullName, new zip.BlobReader(file.Blob), function () {
        file.DataBytes = []
        file.Blob = null

        if (that.currentIndex < that.uploadFiles.length) {
          that.createZip()
        } else {
          that.closeZip()
        }
      })
    },

    closeZip: function () {
      var that = this
      this.zipWriter.close(function (blob) {})
    }
  }

  obj.init(connOpt, options)
  return obj
}

Eci.DownloadResource = {
  Decompressed: '$source$ files processing has been completed.',
  Decompressing: '$source$ files are processing.',
  ConnectionInterrupted: 'Connection interrupted.',
  NotConnected: 'Failed to connect to the server. Please try again later or contact administrator.',
  SingletonSingleFile: '1 $source$ file is downloading ...',
  SingletonMultiFiles: '$file_count$ $source$ files are downloading ...',
  SingletonSingleFileStatus: 'Checking the content of source file ...',
  SingletonMultiFilesStatus: 'Checking the content of source files ...',
  SingletonSingleFileComplete: '1 $source$ file is have been downloaded successfully.',
  SingletonMultiFilesComplete: '$file_count$ $source$ files are have been downloaded successfully.'
}
